﻿using DevExpress.Blazor.Internal;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Text;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.BlobStoring;
using Volo.Abp.Domain.Repositories;
using YAKEJI.Abp.Domain.Repositories;
using YAPACS.BusinessObjects.Exams;
using YAPACS.BusinessObjects.Managements.Exams;
using YAPACS.BusinessObjects.Managements.StoreServices;

namespace YAPACS.RisServer.Controllers;

[Authorize]
[Route("/api/report-image-list")]
public class ReportImageListController : AbpControllerBase
{
    public class ImageDto
    {
        public string Id { get; set; }

        public int? Order { get; set; }

        public string Image { get; set; }
    }

    private readonly IRepository<Report, Guid> _reportRepository;
    private readonly IRepository<ReportImage, Guid> _reportImageRepository;
    private readonly IRepository<Image, Guid> _imageRepository;
    private readonly IRepository<ReportImagePosition, Guid> _reportImagePositionRepository;
    private readonly IRepository<ReportImageDescription, Guid> _reportImageDescriptionRepository;

    public ReportImageListController(
        IRepository<Report, Guid> reportRepository,
        IRepository<ReportImage, Guid> reportImageRepository,
        IRepository<Image, Guid> imageRepository,
        IRepository<ReportImagePosition, Guid> reportImagePositionRepository,
        IRepository<ReportImageDescription, Guid> reportImageDescriptionRepository)
    {
        _reportRepository = reportRepository;
        _reportImageRepository = reportImageRepository;
        _imageRepository = imageRepository;
        _reportImagePositionRepository = reportImagePositionRepository;
        _reportImageDescriptionRepository = reportImageDescriptionRepository;
    }

    [HttpGet("get-image-url")]
    public async Task<string> GetImageUrl([FromQuery] string imageId)
    {
        var image = await _imageRepository.FindAsync(image => image.ImageKey == imageId);
        return image?.JpegUrl;
    }

    [HttpGet("get-images")]
    public async Task<IActionResult> GetImages([FromQuery] Guid reportId)
    {
        var report = await _reportRepository.GetAsync(reportId);
        var studyIds = report.Exam.Studies.Select(s => s.Id).ToList();
        var images = await _imageRepository.GetListAsync(image => image.HasJpeg && studyIds.Contains(image.Series.Study.Id));
        return Ok(new
        {
            Success = true,
            Data = images.OrderBy(image => image.ContentDateTime).Select(image => new
            {
                Id = image.ImageKey,
                Url = image.JpegUrl
            })
        });
    }

    [HttpPost("insert-images")]
    public async Task<IActionResult> InsertImages([FromQuery] Guid reportId, [FromBody] ImageDto[] imageDtos)
    {
        var report = await _reportRepository.GetAsync(reportId);
        var reportImages = report.ReportImages;
        var order = reportImages.OrderBy(image => image.Order).Select(image => image.Order).LastOrDefault();
        var imageIds = imageDtos.Select(dto => dto.Id).ToList();
        foreach (var imageId in imageIds)
        {
            var imageDto = imageDtos.First(x => x.Id == imageId);
            var reportImage = await _reportImageRepository.NewEntityAsync();
            reportImage.ImageKey = imageId;
            reportImage.Report = report;
            reportImage.Order = imageDto.Order ?? (order += 1000);

            var container = report.Exam.StoreService.GetBlobContainer();

            byte[] bytes = null;
            if (string.IsNullOrWhiteSpace(imageDto.Image))
            {
                var image = await _imageRepository.FirstOrDefaultAsync(image => image.ImageKey == imageId);
                if (image != null)
                {
                    bytes = await container.GetAllBytesOrNullAsync(image.JpegPath);
                }
            }
            else
            {
                bytes = Convert.FromBase64String(imageDto.Image);
            }

            if (bytes != null)
            {
                using var stream = new MemoryStream(bytes);
                await container.SaveAsync(reportImage.ImagePath, stream, true);
            }
        }

        return Ok();
    }

    [HttpPost("delete-images")]
    public async Task<IActionResult> DeleteImages([FromBody] string[] imageIds)
    {
        var images = await _imageRepository.GetListAsync(image => imageIds.Contains(image.ImageKey));
        foreach (var image in images)
        {
            var reportImage = await _reportImageRepository.FirstOrDefaultAsync(image => image.ImageKey == image.ImageKey);
            if (reportImage != null)
            {
                await _reportImageRepository.DeleteAsync(reportImage);
            }
            await _imageRepository.DeleteAsync(image);
        }
        return Ok();
    }

    [HttpGet("get-report-images")]
    public async Task<IActionResult> GetReportImages([FromQuery] Guid reportId)
    {
        var report = await _reportRepository.GetAsync(reportId);
        return Ok(new
        {
            Success = true,
            Data = report.ReportImages.OrderBy(image => image.Order).Select(image => new
            {
                Id = image.ImageKey,
                Url = image.ImageUrl,
                image.Position,
                image.Description,
                image.Order,
            })
        });
    }

    [HttpGet("get-report-image-positions")]
    public async Task<IActionResult> GetReportImagePositions([FromQuery] Guid reportId)
    {
        var report = await _reportRepository.GetAsync(reportId);
        var exam = report.Exam;
        var positions = await _reportImagePositionRepository
            .GetListAsync(p => p.Department == exam.Department && p.DeviceType == exam.DeviceType && p.IsActive);
        return Ok(new
        {
            Success = true,
            Data = positions.Select(p => p.Name)
        });
    }

    [HttpGet("get-report-image-descriptions")]
    public async Task<IActionResult> GetReportImageDescriptions([FromQuery] Guid reportId)
    {
        var report = await _reportRepository.GetAsync(reportId);
        var exam = report.Exam;
        var descriptions = await _reportImageDescriptionRepository
            .GetListAsync(p => p.Department == exam.Department && p.DeviceType == exam.DeviceType && p.IsActive);
        return Ok(new
        {
            Success = true,
            Data = descriptions.Select(p => p.Name)
        });
    }

    [HttpPost("sort-report-image")]
    public async Task<IActionResult> SortReportImage([FromQuery] string imageId, [FromQuery] long? order)
    {
        if (order.HasValue)
        {
            var image = await _reportImageRepository.GetAsync(image => image.ImageKey == imageId);
            image.Order = order.Value;
        }
        return Ok();
    }

    [HttpPost("update-report-image")]
    public async Task<IActionResult> UpdateReportImage([FromQuery] string imageId, [FromForm] string data)
    {
        if (!string.IsNullOrWhiteSpace(data))
        {
            var image = await _reportImageRepository.GetAsync(image => image.ImageKey == imageId);
            var container = image.Report.Exam.StoreService.GetBlobContainer();
            var bytes = Convert.FromBase64String(data);
            using var stream = new MemoryStream(bytes);
            await container.SaveAsync(image.ImagePath, stream, true);
        }
        return Ok();
    }

    [HttpPost("update-report-image-info")]
    public async Task<IActionResult> UpdateReportImageInfo([FromQuery] string imageId, [FromForm] string position, [FromForm] string description)
    {
        var image = await _reportImageRepository.GetAsync(image => image.ImageKey == imageId);
        image.Position = position;
        image.Description = description;
        return Ok();
    }

    [HttpPost("update-report-image-position")]
    public async Task<IActionResult> UpdateReportImagePosition([FromQuery] string imageId, [FromForm] string position)
    {
        var image = await _reportImageRepository.GetAsync(image => image.ImageKey == imageId);
        image.Position = position;
        return Ok();
    }

    [HttpPost("update-report-image-description")]
    public async Task<IActionResult> UpdateReportImageDescription([FromQuery] string imageId, [FromForm] string description)
    {
        var image = await _reportImageRepository.GetAsync(image => image.ImageKey == imageId);
        image.Description = description;
        return Ok();
    }

    [HttpPost("delete-report-images")]
    public async Task<IActionResult> DeleteReportImages([FromBody] string[] imageIds)
    {
        var images = await _reportImageRepository.GetListAsync(image => imageIds.Contains(image.ImageKey));
        foreach (var image in images)
        {
            await _reportImageRepository.DeleteAsync(image);
        }
        return Ok();
    }

    [HttpPost("clear-report-images")]
    public async Task<IActionResult> ClearReportImages([FromQuery] Guid reportId)
    {
        var report = await _reportRepository.GetAsync(reportId);
        var reportImages = await _reportImageRepository.GetListAsync(image => image.Report.Id == reportId);
        foreach (var reportImage in reportImages)
        {
            await _reportImageRepository.DeleteAsync(reportImage);
        }
        return Ok();
    }

    [HttpGet("{reportId}/get-study-base-info")]
    public async Task<IActionResult> GetStudyBaseInfo(Guid reportId)
    {
        var report = await _reportRepository.GetAsync(reportId);
        var exam = report.Exam;
        return Ok(new
        {
            Success = true,
            Data = new
            {
                Id = exam.Id.ToString(),
                ReportId = report.Id.ToString(),
                StudyUID = exam.StudyInstanceUid,
                PatientName = exam.Patient.Name,
                DeviceTypeCode = exam.DeviceType.Code,
                Date = exam.CreationTime,
                exam.DeviceType.Modality,
                exam.Patient.PatientId,
                exam.AccessionNumber,
            }
        });
    }
}
